/*
 * Created on 2007-10-21
 *
 * TODO 
 */
package jacky.lanlan.song.extension.struts;

import java.lang.reflect.Method;

/**
 * 路径映射器。
 * <p>
 * 映射URL到Struts Action的执行方法。
 * @author Jacky.Song
 * @see jacky.lanlan.song.extension.struts.AnnotationConfigPlugIn
 * @see jacky.lanlan.song.extension.spring.struts.ConfigStrutsActionBean
 */
public interface URLMethodMapper {

	/**
	 * 提供自定义的Action的执行方法到URL的映射关系。
	 * @param executionMethod String Action的执行方法
	 * @param basePackage 映射该方法访问路径的 basePackage，在配置插件时设置的
	 * @return 对应该方法的URL(相对于Web应用的根路径)
	 */
	public String mapMethodToURL(Method executionMethod,String basePackage);
	
	/**
	 * 默认映射器，提供Ruby-like式的映射规则。
	 * <p/>
	 * 映射规则如下:
	 * <p style="color:red;font-weight:bolder">
	 * 以给定的Action类所在包路径(basePackage)开始，划分Action的子目录。
	 * <br>
	 * 比如有aaa.bbb.Action1和aaa.bbb.ccc.Action2两个Action，在AnnotationConfigPlugIn
	 * 里设置的basePackage为aaa.bbb，则截去aaa.bbb，然后执行以下规则:
	 * </p>
	 * <ul style="color:blue;font-weight:bolder">
	 * 	<li>
	 * 如果Action类名以<em>Action</em>结尾，<em>Action</em>被删除
	 * 	</li>
	 * 	<li>
	 * 方法名：所有大写字母前面加'_'，然后转换为小写
	 * 	</li>
	 * 	<li>
	 * 剩下的包名作为子目录路径，'.'转换为'/'
	 * 	</li>
	 * </ul>
	 * <p style="color:red;font-weight:bolder">
	 * 即：
	 * <br/>
	 * aaa.bbb.MyAction.myMethod ——> /My!my_method.do
	 * <br/>
	 * aaa.bbb.ccc.MyAction.myMethod ——> /ccc/My!my_method.do
	 */
	public URLMethodMapper DEFAULT =new URLMethodMapper() {
		
		public String mapMethodToURL(Method executionMethod,String basePackage) {
			String methodName = executionMethod.getName();//方法名
			String className=executionMethod.getDeclaringClass().getName();//Bean类名
		
			String path = className.replace(basePackage, "").// 取basePackage后面的路径
				replace('.', '/');// '.'转换为'/'
		
			return path.replaceAll("Action$", "") + // 如果以Action结尾，删除Action
					InfrastructureKeys.URL_SEPARATER + // SEPARATER后面跟方法名
					methodName.replaceAll("([A-Z])", "_$1").toLowerCase();// 适当转换方法名
		}
		
	};
	
}
